#pragma once
#include <unordered_map>
#include <memory>

#include "Connection.hpp"
#include "Multiplex.hpp"

class Reactor
{
    static const int gnum = 64;

public:
    Reactor() : _epoller(std::make_unique<Epoller>()), _isrunning(false)
    {
        // 初始化并创建epoller模型
    }
    void AddConnection(int sockfd, uint32_t event, int type, InetAddr addr)
    {
        // 1.构建一个connection
        Connection *conn = new Connection(sockfd, type);
        conn->SetEvent(event);
        conn->SetReactor(this);
        conn->SetAddr(addr);

        // 设置对connection的上层处理，即，如果该connection就绪被激活，我们应该如何处理它？
        if (type == ListenConnection)
        {
            conn->RegisterHandler(_OnConnect, nullptr, nullptr);
        }
        if (type == NormalConnection)
        {
            conn->RegisterHandler(_OnRecver, _OnSender, _OnExcepter);
        }

        // 2.写透到内核中，交给epoll红黑树
        _epoller->AddEvent(sockfd, event);

        // 3.维护_connections
        _connections.insert(std::make_pair(sockfd, conn));
    }
    void DelConnection(int fd)
    {
        // 0.安全检测
        if (!IsConnectionExit(fd))
            return;

        // 1.在内核中移除对fd的关心
        EnableConnectionReadWrite(fd, false, false);
        _epoller->DelEvent(fd);

        // 2.关掉sockfd
        _connections[fd]->Close();

        // 3.在Reactor中移除对fd的关心
        delete _connections[fd];
        _connections.erase(fd);
    }
    void LoopOnce(int timeout)
    {
        int n = _epoller->Wait(_revs, gnum, timeout);
        // 等待成功，派发事件
        for (int i = 0; i < gnum; i++)
        {
            int fd = _revs[i].data.fd;
            uint32_t revent = _revs[i].events;
            if (revent & EPOLLIN)
                if (IsConnectionExit(fd) && _connections[fd]->_handler_recver)
                    _connections[fd]->_handler_recver(_connections[fd]);
            if (revent & EPOLLOUT)
                if (IsConnectionExit(fd) && _connections[fd]->_handler_recver)
                    _connections[fd]->_handler_sender(_connections[fd]);
        }
    }
    void Dispatcher()
    {
        int timeout = -1;
        _isrunning = true;
        while (_isrunning)
        {
            LoopOnce(timeout);

            PrintDebug();
        }
        _isrunning = false;
    }
    bool IsConnectionExit(int fd)
    {
        return _connections.find(fd) != _connections.end();
    }
    void EnableConnectionReadWrite(int fd, bool readble, bool writeble)
    {
        if (!IsConnectionExit(fd))
            return;

        uint32_t event = (readble ? EPOLLIN : 0) | (writeble ? EPOLLOUT : 0) | EPOLLET;

        _connections[fd]->SetEvent(event);

        // 写透到内核中
        _epoller->AddEvent(fd, event);
    }
    void SetOnConnect(handler_t OnConnect)
    {
        _OnConnect = OnConnect;
    }
    void SetNormalHandler(handler_t recver, handler_t sender, handler_t excepter)
    {
        _OnRecver = recver;
        _OnSender = sender;
        _OnExcepter = excepter;
    }
    void PrintDebug()
    {
        std::string fdlist;
        for (auto &conn : _connections)
        {
            fdlist += std::to_string(conn.second->Sockfd()) + " ";
        }
        LOG(DEBUG, "epoll管理的fd列表: %s\n", fdlist.c_str());
    }
    ~Reactor()
    {
    }

private:
    bool _isrunning;
    std::unordered_map<int, Connection *> _connections;
    std::unique_ptr<Multiplex> _epoller;
    struct epoll_event _revs[gnum];

    // Reactor中添加处理socket的方法集合
    // 1. 处理新连接
    handler_t _OnConnect;
    // 2. 处理普通的sockfd，主要是IO处理
    handler_t _OnRecver;
    handler_t _OnSender;
    handler_t _OnExcepter;
};